package org.tsinghua.air.ui;

import java.util.List;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.wb.swt.SWTResourceManager;
import org.tsinghua.air.common.Constant.Database;
import org.tsinghua.air.db.DbConnection;

import swing2swt.layout.BorderLayout;

import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;

public class TableComposite extends Composite {

	private Tree tree;
	private Table table;
	private TableViewer tableViewer;
	private Button btnSave;
	private Button btnDelete;
	private Button btnUpdate;
	protected final Color GRAY = this.getDisplay().getSystemColor(SWT.COLOR_GRAY);
	protected final Color GREEN = this.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN);

	/**
	 * Create the composite.
	 * 
	 * @param parent
	 * @param style
	 */
	public TableComposite(Composite parent, int style) {
		super(parent, SWT.NONE);
		setLayout(new BorderLayout(0, 0));

		createTree();

		createTableComposite();

	}

	private void createTableComposite() {
		Composite composite = new Composite(this, SWT.NONE);
		composite.setLayoutData(BorderLayout.CENTER);
		composite.setLayout(new BorderLayout(0, 0));

		tableViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
		table = tableViewer.getTable();
		table.setTouchEnabled(true);
		table.setLinesVisible(true);
		table.setHeaderVisible(true);
		table.setLayoutData(BorderLayout.CENTER);

		tableViewer.setUseHashlookup(true);

		createButtons(composite);

		final TableEditor editor = new TableEditor(table);
		editor.horizontalAlignment = SWT.LEFT;
		editor.grabHorizontal = true;

		table.addListener(SWT.MouseDown, new TableEditorListener(editor, table, btnSave));

		createTableMenu();

	}

	private void createTableMenu() {
		Menu menu = new Menu(table);
		table.setMenu(menu);

		MenuItem mntmAdd = new MenuItem(menu, SWT.NONE);
		mntmAdd.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				TableItem item = new TableItem(table, SWT.NONE);
				item.setText(0, "+");
				item.setForeground(GREEN);
			}
		});
		mntmAdd.setText("Add");

		MenuItem mntmDelete = new MenuItem(menu, SWT.NONE);
		mntmDelete.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (table.getSelectionIndex() != -1) {
					if (table.getSelection()[0].getText().equals("+")) {
						table.remove(table.getSelectionIndex());
					} else {
						table.getSelection()[0].setText("-");
						table.getSelection()[0].setForeground(GRAY);
					}
				}
			}
		});
		mntmDelete.setText("Delete");

		new MenuItem(menu, SWT.SEPARATOR);

		MenuItem mntmSave = new MenuItem(menu, SWT.NONE);
		mntmSave.setText("Save");
	}

	private void createButtons(Composite composite) {
		Composite btnComposite = new Composite(composite, SWT.NONE);
		btnComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		btnComposite.setLayoutData(BorderLayout.SOUTH);
		btnComposite.setLayout(new FormLayout());

		Button btnAdd = new Button(btnComposite, SWT.CENTER);
		FormData fd_btnAdd = new FormData();
		fd_btnAdd.left = new FormAttachment(100, -221);
		fd_btnAdd.right = new FormAttachment(100, -169);
		fd_btnAdd.bottom = new FormAttachment(100);
		btnAdd.setLayoutData(fd_btnAdd);
		btnAdd.setText("Add");

		btnUpdate = new Button(btnComposite, SWT.CENTER);
		fd_btnAdd.top = new FormAttachment(0);
		btnUpdate.setEnabled(false);
		FormData fd_btnUpdate = new FormData();
		fd_btnUpdate.left = new FormAttachment(100, -163);
		fd_btnUpdate.bottom = new FormAttachment(100);
		fd_btnUpdate.top = new FormAttachment(0);
		btnUpdate.setLayoutData(fd_btnUpdate);
		btnUpdate.setText("Update");

		btnDelete = new Button(btnComposite, SWT.CENTER);
		fd_btnUpdate.right = new FormAttachment(100, -115);
		btnDelete.setEnabled(false);
		FormData fd_btnDelete = new FormData();
		fd_btnDelete.left = new FormAttachment(100, -109);
		fd_btnDelete.bottom = new FormAttachment(100);
		fd_btnDelete.top = new FormAttachment(0);
		btnDelete.setLayoutData(fd_btnDelete);
		btnDelete.setText("Delete");

		btnSave = new Button(btnComposite, SWT.NONE);
		btnSave.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				saveData();
			}
		});
		fd_btnDelete.right = new FormAttachment(100, -61);
		btnSave.setEnabled(false);
		FormData fd_btnSave = new FormData();
		fd_btnSave.left = new FormAttachment(100, -55);
		fd_btnSave.bottom = new FormAttachment(100);
		fd_btnSave.top = new FormAttachment(0);
		fd_btnSave.right = new FormAttachment(100);
		btnSave.setLayoutData(fd_btnSave);
		btnSave.setText("Save");

		Button btnNext = new Button(btnComposite, SWT.NONE);
		btnNext.setEnabled(false);
		FormData fd_btnNext = new FormData();
		fd_btnNext.top = new FormAttachment(0);
		fd_btnNext.left = new FormAttachment(0);
		btnNext.setLayoutData(fd_btnNext);
		btnNext.setText("<");

		Button btnPre = new Button(btnComposite, SWT.NONE);
		btnPre.setEnabled(false);
		FormData fd_btnPre = new FormData();
		fd_btnPre.top = new FormAttachment(0);
		fd_btnPre.left = new FormAttachment(btnNext, 3);
		btnPre.setLayoutData(fd_btnPre);
		btnPre.setText(">");
	}

	private void createTree() {
		tree = new Tree(this, SWT.BORDER);
		tree.setLayoutData(BorderLayout.WEST);
		tree.addListener(SWT.Selection, new Listener() {

			@Override
			public void handleEvent(Event event) {
				TreeItem item = (TreeItem) event.item;

				if (!item.getText().equalsIgnoreCase("Tables")) {
					try {
						createTable(item.getText());
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});

		TreeItem trtmTables = new TreeItem(tree, SWT.NONE);
		trtmTables.setText(new String[] {});
		trtmTables.setText("Tables");

		TreeItem trtmCountry = new TreeItem(trtmTables, SWT.NONE);
		trtmCountry.setText(Database.COUNTRY.toString());

		TreeItem trtmDevelopment = new TreeItem(trtmTables, SWT.NONE);
		trtmDevelopment.setText(Database.DEVELOPMENT_STAGE.toString());

		TreeItem trtmIndustrializationIndex = new TreeItem(trtmTables, SWT.NONE);
		trtmIndustrializationIndex.setText(Database.INDUSTRIALIZATION_INDEX.toString());

		TreeItem trtmLawPolicy = new TreeItem(trtmTables, SWT.NONE);
		trtmLawPolicy.setText(Database.LAW_POLICY.toString());

		TreeItem trtmRuleOfLawIndex = new TreeItem(trtmTables, SWT.NONE);
		trtmRuleOfLawIndex.setText(Database.RULE_OF_LAW_INDEX.toString());

		TreeItem trtmPerEmission = new TreeItem(trtmTables, SWT.NONE);
		trtmPerEmission.setText(Database.PER_EMISSION.toString());

		TreeItem trtmPerGdp = new TreeItem(trtmTables, SWT.NONE);
		trtmPerGdp.setText(Database.PER_GDP.toString());

		TreeItem trtmUrban = new TreeItem(trtmTables, SWT.NONE);
		trtmUrban.setText(Database.URBAN.toString());
		trtmTables.setExpanded(true);

	}

	@Override
	protected void checkSubclass() {
		// Disable the check that prevents subclassing of SWT components
	}

	protected void createTable(String input) throws Exception {
		if (btnSave != null) {
			if (btnSave.isEnabled())
				verifyDataChange();

			btnSave.setEnabled(false);
		}

		String tb = Database.nameToTable(input);
		if (tb == null) {
			throw new Exception("wrong input");
		} else {
			try {
				String[] col = DbConnection.getColumnNames(tb);
				table.setRedraw(false);
				while (table.getColumnCount() > 0) {
					table.getColumns()[0].dispose();
				}
				for (TableItem item : table.getItems()) {
					item.dispose();
				}
				TableColumn column0 = new TableColumn(table, SWT.CENTER, 0); // check
				column0.setText(" ");
				column0.setWidth(20);
				column0.setResizable(false);
				for (int i = 0; i < col.length; i++) {
					TableColumn column = new TableColumn(table, SWT.LEFT, i + 1);
					column.setText(col[i]);
					column.setWidth((int) (col[i].length() * 7.5 + 36));
				}

				// insert data to table
				List<String[]> list = DbConnection.getData(tb);
				for (int i = 0; i < list.size(); i++) {
					TableItem item = new TableItem(table, SWT.NONE);
					item.setText(list.get(i));
				}

				table.setRedraw(true);

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * pass database table information to TableComposite
	 * 
	 * @param db
	 *            : database to select
	 */
	public void selectTable(String db) {
		for (TreeItem it : tree.getItem(0).getItems()) {
			if (it.getText().equals(db)) {
				tree.select(it);
				tree.setFocus();
				// tableViewer.setInput(db);
				try {
					createTable(db);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * save changed data from UI to database
	 */
	protected void saveData() {
		// TODO Auto-generated method stub

	}

	@Override
	public void dispose() {
		verifyDataChange();
		super.dispose();
	}

	private void verifyDataChange() {
		if (btnSave.isEnabled()) {
			boolean result = MessageDialog.openConfirm(this.getShell(), "Data", "Save changed data?");
			if (result == true) {
				saveData();
			}
		}
	}
}

class TableEditorListener implements Listener {
	private final TableEditor editor;
	private Table table;
	private Button btnSave;
	final Color BLUE;

	TableEditorListener(TableEditor editor, Table table, Button btnSave) {
		this.editor = editor;
		this.table = table;
		this.btnSave = btnSave;
		BLUE = table.getDisplay().getSystemColor(SWT.COLOR_BLUE);
	}

	@Override
	public void handleEvent(Event event) {

		if (event.button == 1) {
			if (table.getSelection().length > 0 && !table.getSelection()[0].getText(0).equals("-")) {
				edit(event);
			}
		} else if (event.button == 3) {
			int selectIndex = table.getSelectionIndex();
			if (selectIndex > -1 && !table.getItem(selectIndex).getText().equals("-")) {
				table.getMenu().getItem(1).setEnabled(true);
			} else {
				table.getMenu().getItem(1).setEnabled(false);
			}
		}

	}

	private void edit(Event event) {
		Rectangle clientArea = table.getClientArea();
		Point pt = new Point(event.x, event.y);
		int index = table.getTopIndex();
		while (index < table.getItemCount()) {
			boolean visible = false;
			final TableItem item = table.getItem(index);
			for (int i = 1; i < table.getColumnCount(); i++) { // first column
																// is not data
				Rectangle rect = item.getBounds(i);
				if (rect.contains(pt)) {
					final int column = i;
					final Text text = new Text(table, SWT.NONE);
					Listener textListener = new Listener() {
						@Override
						public void handleEvent(final Event e) {
							switch (e.type) {
							case SWT.FocusOut:
								setText(item, column, text);
								text.dispose();
								break;
							case SWT.Traverse:
								switch (e.detail) {
								case SWT.TRAVERSE_RETURN:
									setText(item, column, text);
									// FALL THROUGH
								case SWT.TRAVERSE_ESCAPE:
									text.dispose();
									e.doit = false;
								}
								break;
							}
						}

						private void setText(final TableItem item, final int column, final Text text) {
							if (!text.getText().equals(item.getText(column))) {
								item.setText(column, text.getText());
								if (item.getText(0).equals("")) {
									item.setText(0, "*");
									item.setForeground(BLUE);
								}
								btnSave.setEnabled(true);
							}
						}
					};
					text.addListener(SWT.FocusOut, textListener);
					text.addListener(SWT.Traverse, textListener);
					editor.setEditor(text, item, i);
					text.setText(item.getText(i));
					text.selectAll();
					text.setFocus();
					return;
				}
				if (!visible && rect.intersects(clientArea)) {
					visible = true;
				}
			}
			if (!visible)
				return;
			index++;
		}
	}
}
